package com.cdqidi.core.weixinmanager.controller.api;

import com.cdqidi.core.weixinmanager.service.wx.WxApiService;
import com.cdqidi.core.weixinmanager.util.FileUtil;
import com.cdqidi.core.weixinmanager.util.Sign;
import com.cdqidi.core.weixinmanager.util.WxApiResult;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.exception.ApiException;
import com.jfinal.springboot.weixin.annotation.ApiType;
import com.jfinal.springboot.weixin.annotation.WxApi;
import com.jfinal.weixin.sdk.api.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.BufferedInputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * APP_微信公众号接口
 *
 * @author sjk
 * @create 2019-06-25 14:26
 * @since 1.0.0
 */
@WxApi(type = ApiType.WX)
@RestController
@RequestMapping("/wxmanager/wxApi/")
@Valid
@Slf4j
@RequiredArgsConstructor
public class WxApiController {
    private final WxApiService wxApiService;

    /**
     * 自定义菜单查询
     *
     * @return 微信返回
     */
    @GetMapping(value = "/getMenu")
    public ApiResultWrapper<Object> getMenu() {
        ApiResult apiResult = MenuApi.getMenu();
        final Map<String, Object> attrs = apiResult.getAttrs();
        if (apiResult.isSucceed()) {
            return com.cdqidi.dto.ApiResult.success(attrs);
        }
        return com.cdqidi.dto.ApiResult.error(apiResult.getErrorCode(), apiResult.getErrorMsg());
    }

    /**
     * 从微信端获得所属行业
     *
     * @return 微信返回
     */
    @GetMapping(value = "/getIndustry")
    public ApiResultWrapper<Object> getIndustry() {
        return WxApiResult.setResponse(TemplateMsgApi.getIndustry());
    }


    /**
     * 获取模板列表
     *
     * @return 微信返回
     */
    @GetMapping(value = "/getAllPrivateTemplate")
    public ApiResultWrapper<Object> getAllPrivateTemplate() {
        return WxApiResult.setResponse(TemplateMsgApi.getAllTemplate());
    }

    /**
     * 发送模板消息
     *
     * @return 微信返回
     */
    @PostMapping(value = "/sendTemplateMsg")
    public ApiResultWrapper<Object> sendTemplateMsg(@RequestBody @NotBlank(message = "jsonStr不能为空") String jsonStr) {
        ApiResult result = TemplateMsgApi.send(jsonStr);
        log.info("msgId,long: {}", result.getLong("msgid"));
        return WxApiResult.setResponse(result);
    }

    /**
     * jssdk鉴权
     *
     * @param url      需要鉴权的url
     * @param isDecode 是否编码
     * @return 编码后的数据
     */
    @GetMapping(value = "/wxJsConfigSign")
    public ApiResultWrapper<Object> wxJsConfigSign(@NotBlank(message = "url不能为空") String url, @NotBlank(message = "isDecode不能为空") Boolean isDecode) {
        if (null == isDecode) {
            isDecode = false;
        }
        if (isDecode) {
            url = URLDecoder.decode(url, StandardCharsets.UTF_8);
        }
        JsTicket ticket = JsTicketApi.getTicket(JsTicketApi.JsApiType.jsapi);
        String appId = ApiConfigKit.getApiConfig().getAppId();
        Map<String, String> map = Sign.sign(ticket.getTicket(), url);
        Map<String, String> signMap = new HashMap<>(4);
        signMap.put("appId", appId);
        signMap.put("nonceStr", map.get("nonceStr"));
        signMap.put("signature", map.get("signature"));
        signMap.put("timestamp", map.get("timestamp"));
        if (log.isDebugEnabled()) {
            log.debug("wxJsConfigSign,url: {},ticket: {},appId: {},nonceStr: {},signature: {},timestamp: {}", url, ticket.getTicket(), appId, map.get("nonceStr"), map.get("signature"), map.get("timestamp"));
        }
        return com.cdqidi.dto.ApiResult.success(signMap);
    }

    /**
     * 下载媒体附件
     *
     * @param mediaId  媒体ID
     * @param response 流
     */
    @GetMapping(value = "/downloadMedia")
    public void downloadMedia(@NotBlank(message = "mediaId不能为空") String mediaId, HttpServletResponse response) {
        final MediaFile mediaFile = MediaApi.getMedia(mediaId);
        if (null == mediaFile) {
            throw new ApiException("下载文件异常");
        }
        try {
            try (BufferedInputStream fileStream = mediaFile.getFileStream()) {
                final byte[] bytes = FileUtil.readStream(fileStream);
                response.setHeader("Cache-Control", "no-store");
                response.setHeader("Pragma", "no-cache");
                response.setHeader("content-disposition", "attachment;filename=\"" + mediaFile.getFullName() + "\"");
                response.setDateHeader("Expires", 0);
                response.setContentType(mediaFile.getContentType());
                try (ServletOutputStream responseOutputStream = response.getOutputStream()) {
                    responseOutputStream.write(bytes);
                    responseOutputStream.flush();
                }
            }
        } catch (Exception e) {
            throw new ApiException(e);
        }
    }

    /**
     * 获得openId
     *
     * @param request  请求
     * @param response 响应
     */
    @GetMapping(value = "/getOpenid")
    public void getOpenid(HttpServletRequest request, HttpServletResponse response) {
        wxApiService.getOpenid(request, response);
    }

    /**
     * 回调
     *
     * @param response    响应
     * @param redirectUri 重定向地址
     * @param scope       snsapi_base不弹出授权页 snsapi_userinfo 弹出授权
     */
    @GetMapping(value = "/redirectAuthorizeUrl")
    public void redirectAuthorizeUrl(HttpServletResponse response, String redirectUri, String path, boolean scope) {
        wxApiService.redirectAuthorizeURL(response, redirectUri, path, scope);
    }

    /**
     * 创建菜单
     *
     * @param jsonStr 菜单json
     * @return 成功 or 失败
     */
    @PostMapping(value = "/createMenu")
    public ApiResultWrapper<Object> createMenu(@Validated @RequestBody String jsonStr) {
        ApiResult menu = MenuApi.createMenu(jsonStr);
        if (menu.isSucceed()) {
            return com.cdqidi.dto.ApiResult.success();
        } else {
            log.error("创建菜单异常,errCode: {},errMsg: {}", menu.getErrorCode(), menu.getErrorMsg());
            return com.cdqidi.dto.ApiResult.error("创建菜单异常");
        }

    }

    /**
     * 添加菜单项
     *
     * @param jsonStr 菜单json
     * @return 成功 or 失败
     */
    @PostMapping(value = "/addConditional")
    public ApiResultWrapper<Object> addConditional(@Validated @RequestBody String jsonStr) {
        MenuApi.addConditional(jsonStr);
        return com.cdqidi.dto.ApiResult.success();
    }

    /**
     * 删除菜单
     *
     * @return 成功 or 失败
     */
    @DeleteMapping(value = "/deleteMenu")
    public ApiResultWrapper<Object> deleteMenu() {
        ApiResult apiResult = MenuApi.deleteMenu();
        if (apiResult.isSucceed()) {
            return com.cdqidi.dto.ApiResult.success();
        } else {
            log.error("删除菜单异常,errCode: {},errMsg: {}", apiResult.getErrorCode(), apiResult.getErrorMsg());
            return com.cdqidi.dto.ApiResult.error("删除菜单异常");
        }
    }

    /**
     * 删除某一项
     *
     * @return 成功 or 失败
     */
    @GetMapping(value = "/delConditional")
    public ApiResultWrapper<Object> delConditional(String menuId) {
        ApiResult apiResult = MenuApi.delConditional(menuId);
        if (apiResult.isSucceed()) {
            return com.cdqidi.dto.ApiResult.success();
        } else {
            log.error("删除菜单项异常,errCode: {},errMsg: {}", apiResult.getErrorCode(), apiResult.getErrorMsg());
            return com.cdqidi.dto.ApiResult.error("删除菜单项异常");
        }
    }

}